package com.googlecode.sqldatagenerator.util;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONTokener;
import org.json.JSONWriter;

public class JsonUtil {

    /**
     * Converte o valor especificado em um texto no formato JSON.
     * 
     * @param value
     *          valor a converter
     *          
     * @return o texto JSON equivalente
     */
    public static String toJson(Object value){
        try {
            if (value == null || value.equals(null)) {
                return "null";
            }
            if (value instanceof Boolean 
                    || value instanceof JSONObject 
                    || value instanceof JSONArray) {
                return value.toString();
            }
            if (value instanceof Map) {
                return new JSONObject((Map<?,?>)value).toString();
            }
            if (value instanceof Collection) {
                return new JSONArray((Collection<?>)value).toString();
            }
            if (value.getClass().isArray()) {
                return new JSONArray(value).toString();
            }
            if (value instanceof JSONString 
                    || value instanceof Number
                    || value.getClass() == String.class) {
                StringWriter r = new StringWriter();
                new JSONWriter(r).array().value(value);
                r.getBuffer().delete(0, 1);
                return r.toString();           
            }
            return new JSONObject(value).toString();
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Converte o texto JSON em objetos Java
     * 
     * @param json
     *          texto a converter
     * 
     * @return o objeto Java equivalente ao JSON
     */
    @SuppressWarnings("unchecked")
    public static Object fromJson(String json) {
        try {
            Object result = new JSONTokener(json).nextValue();
            if (result == null){
                return null;
            }
            if (result.getClass() == JSONObject.class){
                JSONObject jo = (JSONObject) result;
                Map<Object, Object> map = new HashMap<Object, Object>();
                for (Iterator<String> it = jo.keys(); it.hasNext();){
                    String key = it.next();
                    map.put(key, jo.get(key));
                }
                return map;
            }
            if (result.getClass() == JSONArray.class){
                JSONArray ja = (JSONArray) result;
                int length = ja.length();
                ArrayList<Object> list = new ArrayList<Object>(length);
                for (int i=0; i<length; i++){
                    list.add(ja.get(i));
                }
                return list;
            }
            return result;
        } catch (JSONException e) {
            throw new IllegalArgumentException("Invalid JSON", e);
        }
    }

}
